﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sanford.Multimedia.Midi;
using System.Threading;

namespace MusicaTangible
{
    class MusicProcessor
    {
        protected Thread updateThread;
        protected Board board;
        protected Instrument[] instruments;
        protected MidiInternalClock metronome;
        protected int currentColumn;
        protected MainWindow parent;
        protected int tempo;
        public int Tempo
        {
            get
            {
                return this.tempo;
            }
            set
            {
                this.tempo = value;
                this.metronome.Tempo = 12000000 - this.tempo * 500000;
            }
        }
        public bool IsPlaying { get; protected set; }

        public MusicProcessor(MainWindow parent)
        {
            this.parent = parent;
            this.currentColumn = 0;
            this.board = new BoardFromCam(this, 8);
            this.createDefaultIntruments();

            this.metronome = new MidiInternalClock();
            this.Tempo = 1;
            this.metronome.Ppqn = 24;
            this.metronome.Tick += new EventHandler(metronome_Tick);
        }

        private void createDefaultIntruments()
        {
            this.instruments = new Instrument[4];
            instruments[(int)Shapes.circle] = new Instrument("Piano", Instrument.InstrumentPresets.piano);
            instruments[(int)Shapes.square] = new Instrument("Drums", Instrument.InstrumentPresets.drums);
            instruments[(int)Shapes.cross] = new Instrument("Bass", Instrument.InstrumentPresets.bass);
            instruments[(int)Shapes.triangle] = new Instrument("Guitar", Instrument.InstrumentPresets.guitar);
        }

        protected void update()
        {            
            this.board.Update();
        }

        public void UpdateForm()
        {
            for (int i = 0; i < this.board.NumberOfRows; i++)
            {
                this.parent.UpdateInstruments(i, this.board.GetInstrument(i));
                for (int j = 0; j < this.board.NumberofColumms; j++)
                {
                    this.parent.UpdateNotes(i, j, this.board.GetColor(i, j));
                }
            }
        }

        void metronome_Tick(object sender, EventArgs e)
        {
            this.parent.UpdateColumn(this.currentColumn);
            for (int i = 0; i < this.board.NumberOfRows; i++)
            {
                Colors colorAux = this.board.GetColor(i, currentColumn);
                Shapes instrument = this.board.GetInstrument(i);
                if (instrument != Shapes.empty)
                {
                    if (colorAux != Colors.empty)
                    {
                        this.instruments[(int)instrument].Play(colorAux);
                    }
                }
            }
            if (this.currentColumn == 7)
                this.currentColumn = 0;
            else
                this.currentColumn++;

            if (this.currentColumn == 5)
            {
                this.updateThread = new Thread(this.update);
                this.updateThread.Start();
            }

            if (this.currentColumn == 6)
            {
                this.UpdateForm();
                //this.board.printBoard();
            }
             
        }

        public void Play()
        {
            this.IsPlaying = true;
            this.metronome.Start();
        }

        public void Stop()
        {
            this.IsPlaying = false;
            if (this.metronome != null)
                this.metronome.Stop();
            this.board.Stop();
        }
        
    }
}
